package com.tsd.jxc.sale.service.impl;

import com.tsd.base.service.BaseCodeRuleService;
import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.constants.Constants;
import com.tsd.core.constants.VersionConstants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.service.GetDuplicatedObj;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.ErrorCode;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.HttpResult;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.config.JxcCodeRuleConstants;
import com.tsd.jxc.fin.FinanceConstants;
import com.tsd.jxc.fin.dao.JxcFinanceAccountDetailMapper;
import com.tsd.jxc.fin.dao.JxcFinanceAccountMapper;
import com.tsd.jxc.fin.entity.JxcFinanceAccountDetailExt;
import com.tsd.jxc.fin.entity.JxcFinanceAccountExt;
import com.tsd.jxc.fin.job.JxcFinanceJob;
import com.tsd.jxc.sale.dao.JxcSaleOrderMapper;
import com.tsd.jxc.sale.dao.JxcSaleReturnBillDetailMapper;
import com.tsd.jxc.sale.dao.JxcSaleReturnBillMapper;
import com.tsd.jxc.sale.entity.JxcSaleReturnBill;
import com.tsd.jxc.sale.entity.JxcSaleReturnBillDetailExt;
import com.tsd.jxc.sale.entity.JxcSaleReturnBillExt;
import com.tsd.jxc.sale.service.JxcSaleReturnBillDetailService;
import com.tsd.jxc.sale.service.JxcSaleReturnBillService;
import com.tsd.jxc.stock.StockConstants;
import com.tsd.jxc.stock.entity.JxcStockInbillExt;
import com.tsd.jxc.stock.entity.JxcStockInbillItemExt;
import com.tsd.jxc.stock.service.JxcStockGoodsService;
import com.tsd.jxc.stock.service.JxcStockInbillService;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import com.tsd.system.entity.SysUserExt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 描述：JxcSaleReturnBill 服务实现层
 *
 * @author Hillpool
 * @date 2022/07/29 15:04:27
 */
@Service
public class JxcSaleReturnBillServiceImpl extends BaseServiceImpl implements JxcSaleReturnBillService, GetDuplicatedObj {

    @Resource
    private JxcSaleReturnBillMapper jxcSaleReturnBillMapper;
    @Resource
    private JxcSaleReturnBillDetailMapper jxcSaleReturnBillDetailMapper;
    @Resource
    private JxcSaleOrderMapper jxcSaleOrderMapper;
    @Resource
    private JxcFinanceAccountMapper jxcFinanceAccountMapper;
    @Resource
    private JxcFinanceAccountDetailMapper jxcFinanceAccountDetailMapper;
    @Resource
    private BaseCodeRuleService baseCodeRuleService;
    @Resource
    private JxcSaleReturnBillDetailService jxcSaleReturnBillDetailService;
    @Resource
    private JxcStockInbillService jxcStockInbillService;
    @Resource
    private JxcFinanceJob jxcFinanceJob;
    @Resource
    private JxcStockGoodsService jxcStockGoodsService;


    @Override
    public JxcSaleReturnBill getJxcSaleReturnBillById(Long id) throws Exception {
        return jxcSaleReturnBillMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcSaleReturnBillExt queryBySid(String sid) throws Exception {
        JxcSaleReturnBillExt billExt = jxcSaleReturnBillMapper.selectBySid(sid);
        if (billExt != null) {
            List<JxcSaleReturnBillDetailExt> list = jxcSaleReturnBillDetailService.queryValidByReturnList(Collections.singletonList(billExt.getSid()));
            billExt.setDetail_list(list);
        }
        return billExt;
    }

    @Override
    public void deleteJxcSaleReturnBills(List<String> list, SysUser opUser) throws Exception {
        if (HlpUtils.isEmptyList(list)) {
            return;
        }
        BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
        logicVo.setSidList(list);
        jxcSaleReturnBillMapper.deleteLogicBySidList(logicVo);
        // 删除明细
        jxcSaleReturnBillDetailMapper.deleteLogicByReturnList(logicVo);
        // 更新销售订单及明细
        jxcSaleReturnBillDetailService.updateReturn2SaleOrder(list);
    }

    @Override
    public boolean isDuplicated(Object obj, String code) {
        if (obj == null) {
            return false;
        }
        JxcSaleReturnBillExt billExt = (JxcSaleReturnBillExt) obj;
        billExt.setCode(code);
        return jxcSaleReturnBillMapper.selectDuplicatedCode(billExt) != null;
    }

    @Override
    public void saveJxcSaleReturnBill(JxcSaleReturnBillExt record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            if (!HlpUtils.isEmpty(record.getCode())) {
                //如果是手动设置了编号，则检查是否有相同的，有的话，置空后重新生成
                JxcSaleReturnBillExt same = jxcSaleReturnBillMapper.selectDuplicatedCode(record);
                if (same != null) {
                    record.setCode(null);
                }
            }
            String genCode = baseCodeRuleService.genCode(record.getClient_sid(), JxcCodeRuleConstants.TYPE_JXC_SALE_RETURN_BILL, JxcCodeRuleConstants.TYPE_NAME_JXC_SALE_RETURN_BILL, opUser, record.getCode(), record, this);
            record.setCode(genCode);
            record.setState(Constants.VALUE_NO);
            record.setAudit_state(Constants.VALUE_NO);
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE, new Date(), record.getReturn_date());
            jxcSaleReturnBillMapper.insertSelective(record);
        } else {
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            super.updateYyyyMmdd(record, record.getReturn_date());
            jxcSaleReturnBillMapper.updateByPrimaryKeySelective(record);
        }
        jxcSaleReturnBillDetailService.saveJxcSaleReturnBillDetail(record, opUser);
    }

    @Override
    public List<JxcSaleReturnBillExt> findJxcSaleReturnBills(Map<String, Object> params, PageBean page) throws Exception {
        return jxcSaleReturnBillMapper.selectByPage(params, page);
    }

    @Override
    public List<JxcSaleReturnBillExt> findJxcSaleReturnBills(Map<String, Object> params) throws Exception {
        return jxcSaleReturnBillMapper.selectByParams(params);
    }

    @Override
    public HttpResult<String> changeJxcSaleReturnBillAuditState(List<String> sidList, Integer state, SysUserExt opUser) throws Exception {
        JxcSaleReturnBillExt params = new JxcSaleReturnBillExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcSaleReturnBillExt> billExtList = jxcSaleReturnBillMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(billExtList)) {
            return HttpResult.fail(ErrorCode.CODE_PROC_ERROR, "退货单信息为空");
        }
//        List<JxcSaleReturnBillDetailExt> allDetailExts = jxcSaleReturnBillDetailMapper.selectByReturnSidList(sidList);
        if (state == 1) {
            List<JxcSaleReturnBillDetailExt> detailExts = jxcSaleReturnBillDetailMapper.selectOverReturn(sidList);
            if (!HlpUtils.isEmptyList(detailExts)) {
                List<String> nameList = ListUtil.map(detailExts, t -> "销售单号：" + t.getCode() + " 物料：" + t.getName());
                String msg = StringUtils.join(nameList, "、") + " 总退货数量大于销售数量";
                return HttpResult.fail(ErrorCode.CODE_PROC_ERROR, msg);
            }
        }
        boolean isFree = VersionConstants.accountSetVersionIsFree();
        for (JxcSaleReturnBillExt billExt : billExtList) {
            if (state == 1) {
                billExt.setAudit_state(Constants.VALUE_YES);
                billExt.setAuditor_sid(opUser.getSid());
                billExt.setAuditor_name(opUser.getName());
                billExt.setAudit_date(new Date());
                if (isFree) {
                    jxcStockGoodsService.updateBySaleReturnBill(Constants.OP_ADD, billExt);
                }
            } else if (state == -1) {
                billExt.setAudit_state(Constants.VALUE_NO);
                billExt.setAuditor_sid(null);
                billExt.setAuditor_name(null);
                billExt.setAudit_date(null);
                if (isFree) {
                    jxcStockGoodsService.updateBySaleReturnBill(Constants.OP_SUB, billExt);
                }
            }
            jxcSaleReturnBillMapper.updateByPrimaryKey(billExt);
        }
        // 批量更新销售订单及明细
//        List<String> saleOrderList = ListUtil.map(allDetailExts, JxcSaleReturnBillDetailExt::getSale_order_sid);
        if (!HlpUtils.isEmptyList(sidList)) {
            jxcSaleReturnBillDetailService.updateReturn2SaleOrder(sidList);
        }
        return HttpResult.success(null);
    }
//
//    /**
//     * 检查退货数量是否超出销售数量
//     *
//     * @param billExtList
//     * @throws Exception
//     */
//    private void checkReturn(List<JxcSaleReturnBillExt> billExtList) throws Exception {
//        List<String> returnList = ListUtil.map(billExtList, JxcSaleReturnBillExt::getSid);
//        List<JxcSaleReturnBillDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(returnList, list -> jxcSaleReturnBillDetailService.queryValidByReturnList(list));
//        if (HlpUtils.isEmptyList(detailExtList)) {
//            return;
//        }
//        List<String> saleOrderList = ListUtil.map(detailExtList, JxcSaleReturnBillDetailExt::getSale_order_sid);
//        List<JxcSaleOrderExt> orderExtList = ThreadPoolTaskUtil.queryInList4Split(saleOrderList, list -> {
//            JxcSaleOrderExt params = new JxcSaleOrderExt();
//            params.setDr(0);
//            params.setSid_list(list);
//            return jxcSaleOrderMapper.selectByEntity(params);
//        });
//        for (JxcSaleOrderExt orderExt : orderExtList) {
//            List<JxcSaleReturnBillDetailExt> filter = ListUtil.filter(detailExtList, t -> t.getSale_order_sid().equals(orderExt.getSid()));
//            double totalReturn = 0D;
//            for (JxcSaleReturnBillDetailExt ext : filter) {
//                totalReturn = DoubleUtil.add(totalReturn, ext.getQty());
//            }
//            if (!HlpUtils.isEmpty(orderExt.getReturn_qty())) {
//                totalReturn = DoubleUtil.add(totalReturn, orderExt.getReturn_qty());
//            }
//            double value = DoubleUtil.sub(orderExt.getQty(), totalReturn);
//            if (value < 0) {
//                List<String> codeList = ListUtil.map(filter, JxcSaleReturnBillDetailExt::getCode);
//                throw new HlpException("退货单：" + StringUtils.join(codeList, "、") + " 总退货数量大于销售数量");
//            }
//        }
//    }

    @Override
    public void genJxcSaleReturnBill2InBill(List<String> sidList, SysUserExt opUser) throws Exception {
        List<JxcSaleReturnBillExt> billExtList = ThreadPoolTaskUtil.queryInList4Split(sidList, list -> {
            JxcSaleReturnBillExt params = new JxcSaleReturnBillExt();
            params.setDr(0);
            params.setSid_list(list);
            return jxcSaleReturnBillMapper.selectByEntity(params);
        });
        billExtList = ListUtil.filter(billExtList, t -> !StockConstants.IN_OUT_BILL_ALL.equals(t.getIn_bill()));
        if (HlpUtils.isEmptyList(billExtList)) {
            return;
        }
        List<String> billList = ListUtil.map(billExtList, JxcSaleReturnBillExt::getSid);
        List<JxcSaleReturnBillDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(billList, list -> jxcSaleReturnBillDetailService.queryValidByReturnList(list));
        if (HlpUtils.isEmptyList(detailExtList)) {
            return;
        }
        List<JxcSaleReturnBillExt> updateList = new ArrayList<>();
        List<JxcSaleReturnBillDetailExt> updateDetailList = new ArrayList<>();
        for (JxcSaleReturnBillExt billExt : billExtList) {
            List<JxcSaleReturnBillDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getReturn_sid().equals(billExt.getSid()));
            if (HlpUtils.isEmptyList(filterList)) {
                continue;
            }
            billExt.setDetail_list(filterList);
            //TODO 需要获取实际的warehouse_sid
            String warehouse_sid = null;
            JxcStockInbillExt inbillExt = billExt.genInBill(warehouse_sid);
            if (HlpUtils.isEmptyList(inbillExt.getItem_list())) {
                continue;
            }
            jxcStockInbillService.saveJxcStockInbill(inbillExt, opUser);

            billExt.setIn_bill(StockConstants.IN_OUT_BILL_ALL);
            billExt.setIn_bill_sid(inbillExt.getSid());
            super.autoInjectBaseData(billExt, opUser, this.TYPE_UPDATE);
            updateList.add(billExt);

            for (JxcSaleReturnBillDetailExt detailExt : filterList) {
                detailExt.setIn_bill(StockConstants.DETAIL_IN_OUT_BILL_ALL);
                JxcStockInbillItemExt itemExt = ListUtil.get(inbillExt.getItem_list(), t -> t.getSrc_sid().equals(detailExt.getSid()));
                if (itemExt != null) {
                    detailExt.setIn_bill_item_sid(itemExt.getSid());
                }
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_UPDATE);
                updateDetailList.add(detailExt);
            }
        }
        if (!HlpUtils.isEmptyList(updateList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcSaleReturnBillMapper.updateList(itemList));
        }
        if (!HlpUtils.isEmptyList(updateDetailList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateDetailList, false, itemList -> jxcSaleReturnBillDetailMapper.updateList(itemList));
        }
    }

    @Override
    public Integer genJxcFinanceAccountDetail4SaleReturn(List<String> sidList, SysUserExt opUser) throws Exception {
        JxcSaleReturnBillExt params = new JxcSaleReturnBillExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcSaleReturnBillExt> billExtList = jxcSaleReturnBillMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(billExtList)) {
            return 0;
        }
        List<JxcSaleReturnBillExt> filterList = ListUtil.filter(billExtList, t -> !HlpUtils.isEmpty(t.getGen_finance()) && t.getGen_finance() == 1);
        if (!HlpUtils.isEmptyList(filterList)) {
            List<String> codeList = ListUtil.map(billExtList, JxcSaleReturnBillExt::getCode);
            throw new HlpException("销售退货单：" + StringUtils.join(codeList, "、") + " 已生成对账！");
        }

        List<String> clientList = ListUtil.map(billExtList, JxcSaleReturnBillExt::getClient_sid);
        // 查询账户余额
        List<JxcFinanceAccountExt> accountExtList = jxcFinanceAccountMapper.selectValidByPartyList(clientList);
        Map<String, Double> remainAmountMap = new HashMap<>();
        List<JxcSaleReturnBillExt> updateList = new ArrayList<>();
        List<JxcFinanceAccountDetailExt> list = new ArrayList<>();
        String dataSource = DataSourceContextHolder.getDataSourceType();
        for (JxcSaleReturnBillExt billExt : billExtList) {
            JxcFinanceAccountExt accountExt = ListUtil.get(accountExtList, t -> t.getRelated_party_sid().equals(billExt.getClient_sid()));
            List<JxcFinanceAccountDetailExt> detailExtList = billExt.genAccountDetail();
            if (!HlpUtils.isEmptyList(detailExtList)) {
                for (JxcFinanceAccountDetailExt detailExt : detailExtList) {
                    super.autoInjectBaseData(detailExt, opUser, this.TYPE_CREATE);
                    double remainAmount = 0D;
                    if (remainAmountMap.containsKey(billExt.getClient_sid())) {
                        remainAmount = remainAmountMap.get(billExt.getClient_sid());
                    } else if (accountExt != null) {
                        remainAmount = accountExt.getAmount().doubleValue();
                    }
                    if (FinanceConstants.OP_ADD.equals(FinanceConstants.getAccountTypeOp(dataSource, detailExt.getBill_type()))) {
                        remainAmount = DoubleUtil.add(remainAmount, FinanceConstants.getAmount(detailExt));
                    } else {
                        remainAmount = DoubleUtil.sub(remainAmount, FinanceConstants.getAmount(detailExt));
                    }
                    remainAmountMap.put(billExt.getClient_sid(), remainAmount);
                    detailExt.setRemain_amount(BigDecimal.valueOf(remainAmount));
                    String genCode = baseCodeRuleService.genCode(detailExt.getRelated_party_sid(), JxcCodeRuleConstants.TYPE_JXC_FINANCE_ACCOUNT, JxcCodeRuleConstants.TYPE_NAME_JXC_FINANCE_ACCOUNT, opUser, null, null, null);
                    detailExt.setCode(genCode);
                    list.add(detailExt);
                }
            }

            JxcSaleReturnBillExt updateData = new JxcSaleReturnBillExt();
            updateData.setId(billExt.getId());
            updateData.setSid(billExt.getSid());
            updateData.setGen_finance(1);
            super.autoInjectBaseData(updateData, opUser, this.TYPE_UPDATE);
            updateList.add(updateData);
        }

        ThreadPoolTaskUtil.executeInList4Split(list, false, itemList -> jxcFinanceAccountDetailMapper.insertList(itemList));

        // 更新字段：gen_finance
        ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcSaleReturnBillMapper.updateList(itemList));

        // 添加队列
        for (JxcFinanceAccountDetailExt detailExt : list) {
            jxcFinanceJob.addJxcFinanceQue(FinanceConstants.QUEUE_OP_INSERT, FinanceConstants.BIZ_NAME_FINANCE, "updateFinanceAmount", detailExt.getId(), opUser);
        }
        return list.size();
    }

    @Override
    public List<JxcSaleReturnBillExt> findJxcSaleReturnBillsIncludeDetail(Map<String, Object> params, PageBean page) {
        return jxcSaleReturnBillMapper.selectJxcSaleReturnBillsIncludeDetailByPage(params, page);
    }

    @Override
    public List<JxcSaleReturnBillExt> queryJxcSaleReturnBillData4Print(List<String> sidList) throws Exception {
        List<JxcSaleReturnBillExt> list = ThreadPoolTaskUtil.queryInList4Split(sidList, itemList -> {
            JxcSaleReturnBillExt params = new JxcSaleReturnBillExt();
            params.setDr(0);
            params.setSid_list(itemList);
            return jxcSaleReturnBillMapper.selectByEntity(params);
        });
        if (!HlpUtils.isEmptyList(list)) {
            List<String> returnList = ListUtil.map(list, JxcSaleReturnBillExt::getSid);
            List<JxcSaleReturnBillDetailExt> detailExtList = jxcSaleReturnBillDetailService.queryValidByReturnList(returnList);
            for (JxcSaleReturnBillExt billExt : list) {
                List<JxcSaleReturnBillDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getReturn_sid().equals(billExt.getSid()));
                billExt.setDetail_list(filterList);
            }
        }
        return list;
    }

}
